#pragma once

#include <unistd.h>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include <cassert>
#include <sys/epoll.h>
#include <poll.h>

#include "sock.hpp"
#include "epoll.hpp"
#include "Util.hpp"

#define DEFAULTPORT 8080
#define DEFAULTCONNECTION -1


namespace ServerFile
{
    class Connection;
    class Server;

    using fun_t = std::function<void (Connection*)>;

    class Connection
    {
    public:
          Connection(int socket = DEFAULTCONNECTION)
          :_socket(socket)
          ,_Sercon(nullptr)
          {}
          
          ~Connection()
          {}
    public:
         void registerFun(fun_t recver,fun_t sender,fun_t exceper)
         {
               _recver = recver;
               _sender = sender;
               _exceper = exceper;
         }
    
  
    public:   //这边先直接用默认构造函数
        int _socket;
        std::string _readbuffer;
        std::string _writebuffer;

        fun_t _recver;
        fun_t _sender;          //设置注册回调函数，传入指针以操作readbuffer，和writebuffer
        fun_t _exceper;
        
        Server* _Sercon; //Con的回指指针 
    };

    class Server
    {
    public:
          Server(uint16_t port = DEFAULTPORT)
          :_port(port)
          ,_sock()
          ,_epoll()
          {
            _connectHash.clear();
          }

          void init()
          {
               _sock.setSocket();
               _sock.Bind(_port);
               _sock.Listen();
               //accept就要用到多路转接的策略了

               //下面开始构建epoll,把已经设置阻塞的setNonBaock，listensock套接字加入epoll
               _epoll.create();

               
               addConnection(_sock.getListenSocket() , EPOLLIN | EPOLLET , 
               std::bind(&Server::accepter,this,std::placeholders::_1) , nullptr , nullptr);
          }

          void accepter(Connection* conn)
          {}

          void addConnection(int sock , uint32_t event , fun_t recver,fun_t sender,fun_t exceper)
          {
               // 1.创建connect类，然后insert进入 hash中，（先组织后描述）
               if(event & EPOLLET)     Util::setNonBlockSocket(_sock.getListenSocket());
               Connection* Ce = new Connection(sock); 
               Ce->registerFun(recver,sender,exceper);

               _connectHash.insert(std::make_pair(sock,Ce));     
 
               // 2. 将关心的事件加入epoll模型红黑树中
               bool ret = _epoll.ctrlAdd(sock,event);
               assert(ret);
               (void)ret;
          }

          //任务派发
          void disPatch()
          {
               for( ; ; )
               {
                   int n = _epoll.wait();
               }
          }

    private:
    
       uint16_t _port;
       Sock _sock;
       Epoll _epoll;

       std::unordered_map<int,Connection*>  _connectHash;
    };
}